package com.gitee.wsl.ext.string

enum class CRLFKind {
    LF, CRLF, OTHER
}

/**
 * 所有独立的\r或者\n或者\r\n都规范化为\r\n或者\n
 *
 * @param crlf 如果为true，表示规范化为\r\n。如果为false，则表示规范化为\n
 */
fun normalizeCRLF(str: String?, crlf: Boolean): String? {
    return escapeCRLF(str, if (crlf) CRLFKind.CRLF else CRLFKind.LF, null)
}


fun escapeCRLF(str: String?, replaced: String?): String? {
    return escapeCRLF(str, CRLFKind.OTHER, replaced)
}

private fun escapeCRLF(str: String?, kind: CRLFKind?, replaced: String?): String? {
    if (str == null || str.length <= 0) return str
    var action = 0 // 1 for \r, 2 for \n, 3 for \r\n
    val sz = str.length
    var buf: StringBuilder? = null
    var i = 0
    while (i < sz) {
        val ch = str.get(i)
        if (i == sz - 1) {
            if (ch == '\r') {
                action = 1
            } else if (ch == '\n') {
                action = 2
            } else {
                action = 0
            }
        } else {
            if (ch == '\r') {
                val next = str.get(i + 1)
                if (next == '\n') {
                    action = 3
                } else {
                    action = 1
                }
            } else if (ch == '\n') {
                action = 2
            } else {
                action = 0
            }
        }

        if (buf != null) {
            if (action == 0) {
                buf.append(ch)
            } else {
                if (action == 3) i++
                if (kind == CRLFKind.CRLF) {
                    buf.append('\r').append('\n')
                } else if (kind == CRLFKind.LF) {
                    buf.append('\n')
                } else {
                    buf.append(replaced)
                }
            }
        } else {
            if (action == 2) {
                if (kind == CRLFKind.LF) {
                    i++
                    continue
                }
            } else if (action == 3) {
                if (kind == CRLFKind.CRLF) {
                    i++
                    i++
                    continue
                }
            }

            if (action != 0) {
                if (buf == null) {
                    buf = StringBuilder(2 * sz)
                    if (i > 0) buf.append(str.subSequence(0, i))
                }
                if (action == 3) i++

                if (kind == CRLFKind.CRLF) {
                    buf.append('\r').append('\n')
                } else if (kind == CRLFKind.LF) {
                    buf.append('\n')
                } else {
                    buf.append(replaced)
                }
            }
        }
        i++
    }

    if (buf == null) return str
    return buf.toString()
}